/*
 * 
 */
package com.yuanmei.stockeyes.charts;

import android.content.Context;
import android.graphics.Color;
import android.graphics.PointF;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.style.ForegroundColorSpan;
import android.util.Log;
import android.view.View;
import android.view.View.OnTouchListener;

import com.tictactec.ta.lib.Core;
import com.tictactec.ta.lib.MInteger;
import com.tictactec.ta.lib.RetCode;
import com.yuanmei.stockeyes.R;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import cn.limc.androidcharts.entity.DateValueEntity;
import cn.limc.androidcharts.entity.LineEntity;
import cn.limc.androidcharts.event.IDisplayCursorListener;
import cn.limc.androidcharts.view.SlipMinusLineChart;

public class TalibAdxChart implements ITalibChart {
    private final Core mTaLibCore = new Core();
    private Context mContext;
    private SlipMinusLineChart mAdxChartView;
    private static final String TAG = TalibAdxChart.class.getName();

    private List<DateValueEntity> mAdxDateValueList;
    private LineEntity<DateValueEntity> mAdxLineEntity;

    private List<DateValueEntity> mPlusDiDateValueList;
    private LineEntity<DateValueEntity> mPlusDiLineEntity;

    private List<DateValueEntity> mMinusDiDateValueList;
    private LineEntity<DateValueEntity> mMinusDiLineEntity;


    private int    mAdxPeriod = 3;
    private String mAdxPeriodName;

    private int mTaIdxDataSetsBegin;
    private int mTaIdxDataSetsNumber;

    public TalibAdxChart(Context context) {
        mAdxChartView = new SlipMinusLineChart(context);
        TalibChartFactory.commonInitGridChart(mAdxChartView);
        TalibChartFactory.commonInitSlipLineChart(mAdxChartView);

        mContext       = mAdxChartView.getContext();
        mAdxPeriodName = mContext.getString(R.string.param_adx_period);
    }

    @Override
    public List<Map<String, Object>> getTaParamsList() {
        List<Map<String, Object>> outParamsList = new ArrayList<Map<String, Object>>();

        Map<String, Object> item = new HashMap<String, Object>();
        item.put(ITalibChart.ITaParamNameKey,  mAdxPeriodName);
        item.put(ITalibChart.ITaParamValueKey, mAdxPeriod);
        outParamsList.add(item);
 

        return outParamsList;
    }

    @Override
    public void setTaParams(Hashtable<String, Integer> inParamMaps) {
        if (inParamMaps.containsKey(mAdxPeriodName)
                ) {
            mAdxPeriod = inParamMaps.get(mAdxPeriodName);
        }
    }

    @Override
    public boolean reloadData(int dataLen,
                              float[] openPrices,
                              float[] highPrices,
                              float[] lowPrices,
                              float[] closePrices,
                              float[] volumes,
                              float[] amounts,
                              int[] dates) {
        MInteger outAdxBegIdx    = new MInteger();
        MInteger outAdxNBElement = new MInteger();
        double[] outValues       = new double[dataLen];
        RetCode retCode = mTaLibCore.adx(0, closePrices.length - 1,
                highPrices, lowPrices, closePrices,
                mAdxPeriod,
                outAdxBegIdx, outAdxNBElement, outValues);
        if (retCode != RetCode.Success) {
            Log.e(TAG, "ADX calc error retCode=" + retCode);
            return false;
        }

        mAdxDateValueList = new ArrayList<>();
        for (int i = 0; i < dataLen; i++) {
            if (i < outAdxBegIdx.value) {
                mAdxDateValueList.add(new DateValueEntity(
                        (float) (outValues[0]), dates[i]));
            } else {
                int idx = i - outAdxBegIdx.value;
                mAdxDateValueList.add(new DateValueEntity(
                        (float) (outValues[idx]), dates[i]));
            }
        }

        /*
        *
   public RetCode plusDI( int startIdx,
      int endIdx,
      double inHigh[],
      double inLow[],
      double inClose[],
      int optInTimePeriod,
      MInteger outBegIdx,
      MInteger outNBElement,
      double outReal[] )
        * */
        MInteger outPlusDIBegIdx    = new MInteger();
        MInteger outPlusDiNBElement = new MInteger();
        retCode = mTaLibCore.plusDI(0, closePrices.length - 1,
                highPrices, lowPrices, closePrices,
                mAdxPeriod,
                outPlusDIBegIdx, outPlusDiNBElement, outValues);
        if (retCode != RetCode.Success) {
            Log.e(TAG, "PLUS DI calc error retCode=" + retCode);
            return false;
        }

        mPlusDiDateValueList = new ArrayList<>();
        for (int i = 0; i < dataLen; i++) {
            if (i < outPlusDIBegIdx.value) {
                mPlusDiDateValueList.add(new DateValueEntity(
                        (float) (outValues[0]), dates[i]));
            } else {
                int idx = i - outPlusDIBegIdx.value;
                mPlusDiDateValueList.add(new DateValueEntity(
                        (float) (outValues[idx]), dates[i]));
            }
        }

        MInteger outMinusDIBegIdx    = new MInteger();
        MInteger outMinusDiNBElement = new MInteger();
        retCode = mTaLibCore.minusDI(0, closePrices.length - 1,
                highPrices, lowPrices, closePrices,
                mAdxPeriod,
                outMinusDIBegIdx, outMinusDiNBElement, outValues);
        if (retCode != RetCode.Success) {
            Log.e(TAG, "MINUS DI calc error retCode=" + retCode);
            return false;
        }

        mMinusDiDateValueList = new ArrayList<>();
        for (int i = 0; i < dataLen; i++) {
            if (i < outMinusDIBegIdx.value) {
                mMinusDiDateValueList.add(new DateValueEntity(
                        (float) (outValues[0]), dates[i]));
            } else {
                int idx = i - outMinusDIBegIdx.value;
                mMinusDiDateValueList.add(new DateValueEntity(
                        (float) (outValues[idx]), dates[i]));
            }
        }

        List<LineEntity<DateValueEntity>> lines = new ArrayList<LineEntity<DateValueEntity>>();

        mAdxLineEntity = new LineEntity<DateValueEntity>();
        mAdxLineEntity.setTitle("ADX");
        mAdxLineEntity.setLineColor(Color.WHITE);
        mAdxLineEntity.setLineData(mAdxDateValueList);
        lines.add(mAdxLineEntity);

        mPlusDiLineEntity = new LineEntity<DateValueEntity>();
        mPlusDiLineEntity.setTitle("DI+");
        mPlusDiLineEntity.setLineColor(Color.RED);
        mPlusDiLineEntity.setLineData(mPlusDiDateValueList);
        lines.add(mPlusDiLineEntity);

        mMinusDiLineEntity = new LineEntity<DateValueEntity>();
        mMinusDiLineEntity.setTitle("DI+");
        mMinusDiLineEntity.setLineColor(Color.GREEN);
        mMinusDiLineEntity.setLineData(mMinusDiDateValueList);
        lines.add(mMinusDiLineEntity);

        mAdxChartView.setLinesData(lines);

        mTaIdxDataSetsBegin  = Math.max(outAdxBegIdx.value,
                Math.max(outPlusDIBegIdx.value, outMinusDIBegIdx.value));
        mTaIdxDataSetsNumber = Math.min(outAdxNBElement.value,
                Math.min(outPlusDiNBElement.value, outMinusDiNBElement.value));
        return true;
    }

    @Override
    public int getTaIndexNumber() {
        return mTaIdxDataSetsNumber;
    }

    @Override
    public String getTaIndexParms() {
        return   mAdxPeriod + "" ;
    }

    @Override
    public String getTaIndexShortName() {
        return "ADX";
    }

    @Override
    public Spanned getTaIndexDetail() {
        if (null == mAdxDateValueList) {
            return new SpannableString("----");
        }
        int index = mAdxChartView.getSelectedIndex();

        DateValueEntity adxEntity = mAdxDateValueList.get(index);
        String          adxText   = String.format(Locale.ENGLISH, "ADX:%.2f ",
                adxEntity.getValue());

        DateValueEntity plusDiEntity = mPlusDiDateValueList.get(index);
        String          plusDiText   = String.format(Locale.ENGLISH, "DI+:%.2f ",
                plusDiEntity.getValue());

        DateValueEntity minusDiEntity = mMinusDiDateValueList.get(index);
        String          minusDiText   = String.format(Locale.ENGLISH, "DI-:%.2f ",
                minusDiEntity.getValue());


        String    finalString = adxText + plusDiText + minusDiText;
        Spannable sb          = new SpannableString(finalString);

        sb.setSpan(new ForegroundColorSpan(mAdxLineEntity.getLineColor()), finalString.indexOf(adxText),
                finalString.indexOf(adxText) + adxText.length(), Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
        sb.setSpan(new ForegroundColorSpan(mPlusDiLineEntity.getLineColor()), finalString.indexOf(plusDiText),
                finalString.indexOf(plusDiText) + plusDiText.length(), Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
        sb.setSpan(new ForegroundColorSpan(mMinusDiLineEntity.getLineColor()), finalString.indexOf(minusDiText),
                finalString.indexOf(minusDiText) + minusDiText.length(), Spanned.SPAN_EXCLUSIVE_INCLUSIVE);

        return (sb);
    }

    @Override
    public int getTaIndexBegin() {
        return mTaIdxDataSetsBegin;
    }

    @Override
    public View getChartView() {
        return mAdxChartView;
    }

    @Override
    public void setDisplayFrom(int from) {
        mAdxChartView.setDisplayFrom(from);
    }

    @Override
    public void setDisplayCrossXOnTouch(boolean displayCrossXOnTouch) {
        mAdxChartView.setDisplayCrossXOnTouch(displayCrossXOnTouch);
    }

    @Override
    public void setDisplayNumber(int number) {
        mAdxChartView.setDisplayNumber(number);
    }

    @Override
    public void setOnTouchListener(OnTouchListener l) {
        mAdxChartView.setOnTouchListener(l);
    }

    @Override
    public void setOnDisplayCursorListener(
            IDisplayCursorListener l) {
        mAdxChartView.setOnDisplayCursorListener(l);
    }

    @Override
    public PointF getTouchPoint() {
        return mAdxChartView.getTouchPoint();
    }

    @Override
    public void setTouchPoint(PointF touchPoint) {
        mAdxChartView.setTouchPoint(touchPoint);
    }

    @Override
    public void postInvalidate() {
        mAdxChartView.postInvalidate();
    }

    @Override
    public float getValidMiddleY() {
        return mAdxChartView.getValidMiddleY();
    }
}
